﻿using Game.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.UI;

namespace Game.Web.Pay.WX
{
    public class WxJsApiHelper
    {
        //公众账号ID
        private static string appid
        {
            get { return ApplicationSettings.Get("WXNATIVEAPPID"); }            
        }
        //商户号
        private static string mch_id
        {
            get { return ApplicationSettings.Get("WXNATIVEMCHID"); }            
        }
        //密钥
        private static string key
        {
            get { return ApplicationSettings.Get("WXNATIVEKEY"); }            
        }
        //公众帐号secert
        private static string appsecret
        {
            get { return ApplicationSettings.Get("WXNATIVESECRET"); }            
        }

        /// <summary>
        /// 保存页面对象，因为要在类的方法中使用Page的Request对象
        /// </summary>
        private Page page { get; set; }

        /// <summary>
        /// openid用于调用统一下单接口
        /// </summary>
        public string openid { get; set; }

        /// <summary>
        /// unionid用户应用帐号互通
        /// </summary>
        public string unionid { get; set; }

        /// <summary>
        /// 用户昵称
        /// </summary>
        public string nickname { get; set; }

        /// <summary>
        /// 用户的性别，值为1时是男性，值为2时是女性，值为0时是未知
        /// </summary>
        public int sex { get; set; }

        /// <summary>
        /// access_token用于获取收货地址js函数入口参数
        /// </summary>
        public string access_token { get; set; }

        public WxJsApiHelper(Page page)
        {
            this.page = page;
        }

        /**
        * 
        * 网页授权获取用户基本信息的全部过程
        * 详情请参看网页授权获取用户基本信息：http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
        * 第一步：利用url跳转获取code
        * 第二步：利用code去获取openid和access_token
        * 
        */
        public string GetOpenidAndAccessToken()
        {
            if (!string.IsNullOrEmpty(page.Request.QueryString["code"]))
            {
                //获取code码，以获取openid和access_token
                string code = page.Request.QueryString["code"];
                Log.Debug(this.GetType().ToString(), "Get code : " + code);
                GetOpenidAndAccessTokenFromCode(code);
                return "";
            }

            //构造网页授权获取code的URL
            string host = page.Request.Url.Host;
            string path = page.Request.Path;
            int gameID = GameRequest.GetQueryInt("GameID", 0);
            string redirect_uri = HttpUtility.UrlEncode("http://" + host + path + "?GameID=" + gameID);
            SortedDictionary<string, object> dic = new SortedDictionary<string, object>();
            dic.Add("appid", appid);
            dic.Add("redirect_uri", redirect_uri);
            dic.Add("response_type", "code");
            dic.Add("scope", "snsapi_userinfo");
            dic.Add("state", gameID + "#wechat_redirect");
            string url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + ToUrl(dic);
            Log.Debug(this.GetType().ToString(), "Will Redirect to URL : " + url);
            return url;
        }


        /**
	    * 
	    * 通过code换取网页授权access_token和openid的返回数据，正确时返回的JSON数据包如下：
	    * {
	    *  "access_token":"ACCESS_TOKEN",
	    *  "expires_in":7200,
	    *  "refresh_token":"REFRESH_TOKEN",
	    *  "openid":"OPENID",
	    *  "scope":"SCOPE",
	    *  "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
	    * }
	    * 其中access_token可用于获取共享收货地址
	    * openid是微信支付jsapi支付接口统一下单时必须的参数
        * 更详细的说明请参考网页授权获取用户基本信息：http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
        * @失败时抛异常WxPayException
	    */
        public void GetOpenidAndAccessTokenFromCode(string code)
        {
            try
            {
                //构造获取openid及access_token的url
                SortedDictionary<string, object> dic = new SortedDictionary<string, object>();
                dic.Add("appid", appid);
                dic.Add("secret", appsecret);
                dic.Add("code", code);
                dic.Add("grant_type", "authorization_code");
                string url = "https://api.weixin.qq.com/sns/oauth2/access_token?" + ToUrl(dic);

                //请求url以获取数据
                string result = HttpService.Get(url);

                Log.Debug(this.GetType().ToString(), "GetOpenidAndAccessTokenFromCode response : " + result);

                //保存access_token，用于收货地址获取
                JObject jd = (JObject)JsonConvert.DeserializeObject(result);
                access_token = (string)jd["access_token"];

                //获取用户openid
                openid = (string)jd["openid"];
                //获取用户unionid
                if (jd["unionid"] == null)
                {
                    unionid = "";
                }
                else
                {
                    unionid = (string)jd["unionid"];
                }

                Log.Debug(this.GetType().ToString(), "Get openid : " + openid);
                Log.Debug(this.GetType().ToString(), "Get access_token : " + access_token);
            }
            catch (Exception ex)
            {
                Log.Error(this.GetType().ToString(), ex.ToString());
                throw new WxPayException(ex.ToString());
            }
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        public void GetUserInfo()
        {
            try
            {
                //构造获取用户信息的url
                SortedDictionary<string, object> dic = new SortedDictionary<string, object>();
                dic.Add("access_token", access_token);
                dic.Add("openid", openid);
                dic.Add("lang", "zh_CN");
                string url = "https://api.weixin.qq.com/sns/userinfo?" + ToUrl(dic);

                //请求url以获取数据
                string result = HttpService.Get(url);

                Log.Debug(this.GetType().ToString(), "GetUserInfo response : " + result);

                JObject jd = (JObject)JsonConvert.DeserializeObject(result);
                nickname = (string)jd["nickname"];
                sex = (int)jd["sex"];
            }
            catch (Exception ex)
            {
                Log.Error(this.GetType().ToString(), ex.ToString());
                throw new WxPayException(ex.ToString());
            }
        }

        public static string GetMakeSign(SortedDictionary<string, object> dic)
        {
            //转url格式
            string str = ToUrl(dic);
            //在string后加入API KEY
            str += "&key=" + key;
            //MD5加密
            var md5 = MD5.Create();
            var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
            var sb = new StringBuilder();
            foreach (byte b in bs)
            {
                sb.Append(b.ToString("x2"));
            }
            //所有字符转为大写
            return sb.ToString().ToUpper();
        }

        /**
        * @Dictionary格式转化成url参数格式
        * @ return url格式串, 该串不包含sign字段值
        */
        public static string ToUrl(SortedDictionary<string, object> m_values)
        {
            string buff = "";
            foreach (KeyValuePair<string, object> pair in m_values)
            {
                if (pair.Value != null && pair.Key != "sign" && pair.Value.ToString() != "")
                {
                    buff += pair.Key + "=" + pair.Value + "&";
                }
            }
            buff = buff.Trim('&');
            return buff;
        }

        /// <summary>
        /// 获取随机数
        /// </summary>
        public static string GetNonce_str()
        {
            return Guid.NewGuid().ToString().Replace("-", "");
        }
        

    }
}